use std::{rc::Rc, cell::RefCell};

use crate::{instructions::base::{Instruction, BytecodeReader}, rtda::Frame};

// 和instanceof指令很像，区别在于：instanceof指令会改变操作数栈（弹出对象引用，推入判断结果）; checkcast则不改变操作数栈（如果判断失败，直接抛出ClassCastException异常）。

#[derive(Debug, Default)]
pub struct CHECK_CAST {
    index: usize
}

impl Instruction for CHECK_CAST {
    fn fetch_operands(&mut self, reader: &mut BytecodeReader) {
        self.index = reader.read_u16() as usize;
    }

    fn execute(&mut self, frame: Rc<RefCell<Frame>>) {
        let stack = frame.borrow().get_operand_stack();
        let _ref = stack.borrow_mut().pop_ref();
        stack.borrow_mut().push_ref(_ref.clone()); // TODO 此处可替换直接获取，而不是先出栈再入栈
        if _ref.is_none() {
            return;
        }
        let _ref = _ref.unwrap();

        let cp = frame.borrow().get_method().get_class().get_constant_pool().unwrap();
        let class_ref = cp.get_constant(self.index).unwrap().class_ref();
        let class = class_ref.lock().unwrap().resolved_class();
        if !unsafe { &*_ref }.is_instance_of(class) {
            panic!("java.lang.ClassGastException")
        }
    }


}
